/*
 * app_hub_api_subsidiary.c
 *
 *  Created on: 2023年7月27日
 *      Author: HXF
 */

#include "app_hub_api_subsidiary.h"
#include "app_log.h"
#include "app_hub_api_usart_event.h"
#include "app_hub_api_rf_event.h"
#include "device.h"
#include "softwareMultiTimer.h"
#include "string.h"
#include "em_chip.h"
#include "btl_reset_info.h"
#include "mac_receiver.h"
#include "net_aseq.h"
#include "cJSON.h"
#include "sl_malloc.h"
#include "stdlib.h"
#include "app_filetransport_api.h"
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)

#include "device_nvm.h"
#include "device_rfmid.h"
#include "device_partition.h"

static int in_output[2] = {0};
static unsigned char in_output_flag = 0;
static int temp_humi[4] = {0};
static unsigned char temp_humi_flag = 0;
static int volt_c_power[5] = {0};
static unsigned char volt_c_power_flag = 0;
static int run_energy[8] = {0};
static unsigned char run_energy_flag = 0;
static int key_press[1] = {0};
static unsigned char key_press_flag = 0;
static int key_multi_press[32] = {0};
static int key_multi_press_num = 0;
static unsigned char key_multi_press_flag = 0;

static bool bc_delete = false;
static bool can_delete = false;
static unsigned char delete_rfmid = 0;
static MultiTimer delet_rfm_Timer = {.Handle = 0x07};
#endif

const unsigned char auchCRCHi[] =
{
  0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
  0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
  0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
  0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
  0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
};

/* CRC低位字节值表*/
const unsigned char auchCRCLo[] =
{
  0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
  0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
  0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
  0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
  0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
  0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
  0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
  0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
  0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
  0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
  0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
  0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
  0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
  0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
  0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
  0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
  0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
  0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
  0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
  0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
  0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
  0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
  0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
  0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
  0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
  0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};


/*
* 函数名 :CRC16
* 描述 : 计算CRC16
* 输入 : msg---数据地址,len---数据长度
* 输出 : 校验值
*/
unsigned short get_msg_crc16(unsigned char *msg, int len)
{
  unsigned char crc_hi = 0xFF ;              // 高CRC字节初始化
  unsigned char crc_lo = 0xFF ;              // 低CRC 字节初始化

  unsigned char idx ;

  if(!msg || !len){
      return 0xffff;
  }
  while (len--)
  {
    idx = crc_hi ^ *msg++ ;
    crc_hi = crc_lo ^ auchCRCHi[idx];
    crc_lo = auchCRCLo[idx];
  }
  return (crc_hi << 8 | crc_lo);
}

unsigned char get_rfmid_from_catno(unsigned char cat, unsigned char no)
{
  unsigned char rfmid = 0xff;
  switch(cat){
    case CAT_IO:
      if(no < DEVICE_TYPE_IO_CN){
          rfmid = RFMID_EN_INDEX_IO_FIRST + no;
      }
      break;
    case CAT_SOUNDER:
      if(no < DEVICE_TYPE_SOUNDER_CN){
          rfmid = RFMID_EN_INDEX_SOUNDER_FIRST + no;
      }
      break;
    case CAT_KEYPAD:
      if(no < DEVICE_TYPE_KEYPAD_CN){
          rfmid = RFMID_EN_INDEX_KEYPAD_FIRST + no;
      }
      break;
    case CAT_FOB:
      if(no < DEVICE_TYPE_FOB_CN){
          rfmid = RFMID_EN_INDEX_FOB_FIRST + no;
      }
      break;
    default:
      break;
  }
  return rfmid;
}

unsigned char get_cat_from_rfmid(unsigned char rfmid)
{
  unsigned char cat = 0xff;
  if(rfmid > RFMID_EN_INDEX_FOB_LAST){  //超过FOB ID

  }else if(rfmid > RFMID_EN_INDEX_KEYPAD_LAST){
      cat = CAT_FOB;
  }else if(rfmid > RFMID_EN_INDEX_SOUNDER_LAST){
      cat = CAT_KEYPAD;
  }else if(rfmid > RFMID_EN_INDEX_IO_LAST){
      cat = CAT_SOUNDER;
  }else if(rfmid >= RFMID_EN_INDEX_IO_FIRST){
      cat = CAT_IO;
  }else{

  }
  return cat;
}

unsigned char get_no_from_cat_rfmid(unsigned char cat, unsigned char rfmid)
{
  unsigned char no = 0xff;
  switch(cat){
    case CAT_IO:
      if(rfmid >= RFMID_EN_INDEX_IO_FIRST && rfmid <= RFMID_EN_INDEX_IO_LAST){
          no = rfmid - RFMID_EN_INDEX_IO_FIRST;
      }
      break;
    case CAT_SOUNDER:
      if(rfmid >= RFMID_EN_INDEX_SOUNDER_FIRST && rfmid <= RFMID_EN_INDEX_SOUNDER_LAST){
          no = rfmid - RFMID_EN_INDEX_SOUNDER_FIRST;
      }
      break;
    case CAT_KEYPAD:
      if(rfmid >= RFMID_EN_INDEX_KEYPAD_FIRST && rfmid <= RFMID_EN_INDEX_KEYPAD_LAST){
          no = rfmid - RFMID_EN_INDEX_KEYPAD_FIRST;
      }
      break;
    case CAT_FOB:
      if(rfmid >= RFMID_EN_INDEX_FOB_FIRST && rfmid <= RFMID_EN_INDEX_FOB_LAST){
          no = rfmid - RFMID_EN_INDEX_FOB_FIRST;
      }
      break;
    default:
      break;
  }
  return no;
}

bool check_rfmid_is_registered(unsigned char rfmid)
{
  unsigned char info[NODE_JOIN_INFO_LENGTH] = {0};
  unsigned char idx = (rfmid - 1)/8;
  unsigned char bit = (rfmid - 1)%8;

  if(getThisParam(ENbyNodeJoinInfo, (unsigned char *)info)){
      if(hub_log_enable){
          DS_app_log_error("ENbyNodeJoinInfo get err, use default value\r\n");
      }
  }

  if(HUB_API_GET_BIT(info[idx], bit)){
      return true;
  }
  return false;
}

bool check_hub_event_need_rtns(void)
{
  bool bret = false;
  unsigned char rtns = 0;
  unsigned char flag = 0;
  unsigned char enable_retrans = 0;
  getThisParam(ENbyEvtA0TNS, (unsigned char *)&rtns);
  getThisParam(ENbyEvtA0AckFlag, (unsigned char *)&flag);
  getThisParam(ENbyEnableRetrans, (unsigned char *)&enable_retrans);
  if((rtns < 2 && flag) && (enable_retrans)){
      bret = true;
  }
  return bret;
}

bool check_hub_event_is_finsih(void)
{
  bool bret = false;
  unsigned char flag = 0;
  getThisParam(ENbyEvtA0AckFlag, (unsigned char *)&flag);
  if(!flag){
      bret = true;
  }
  return bret;
}

bool check_rfm_event_need_rtns(void)
{
  bool bret = false;
  unsigned char rtns = 0;
  unsigned char flag = 0;
  unsigned char enable_retrans = 0;
  getThisParam(ENbyEvtA1TNS, (unsigned char *)&rtns);
  getThisParam(ENbyEvtA1AckFlag, (unsigned char *)&flag);
  getThisParam(ENbyEnableRetrans, (unsigned char *)&enable_retrans);
  if((rtns < 2 && flag) && (enable_retrans)){
      bret = true;
  }
  return bret;
}

bool check_rfm_event_is_finsih(void)
{
  bool bret = false;
  unsigned char flag = 0;
  getThisParam(ENbyEvtA1AckFlag, (unsigned char *)&flag);
  if(!flag){
      bret = true;
  }
  return bret;
}

bool check_file_event_need_rtns(void)
{
  bool bret = false;
  unsigned char rtns = 0;
  unsigned char flag = 0;
  unsigned char enable_retrans = 0;
  getThisParam(ENbyEvtA2TNS, (unsigned char *)&rtns);
  getThisParam(ENbyEvtA2AckFlag, (unsigned char *)&flag);
  getThisParam(ENbyEnableRetrans, (unsigned char *)&enable_retrans);
  if((rtns < 2 && flag) && (enable_retrans)){
      bret = true;
  }
  return bret;
}

bool check_file_event_is_finsih(void)
{
  bool bret = false;
  unsigned char flag = 0;
  getThisParam(ENbyEvtA2AckFlag, (unsigned char *)&flag);
  if(!flag){
      bret = true;
  }
  return bret;
}

static unsigned char reset_enable = 0;
void set_reset_enable(unsigned char state)
{
  reset_enable = state;
}

unsigned char get_reset_enable(void)
{
  return reset_enable;
}

void hub_do_reset(void)
{
  if(!get_reset_enable()){
      return;
  }
  unsigned char reset_mode = 0xff;
  BootloaderResetCause_t* resetCause = (BootloaderResetCause_t*) (SRAM_BASE);
  getThisParam(ENbyResetMode, &reset_mode);
  if(reset_mode == SOFT_RESET){
      if(hub_log_enable){
          DS_app_log_error("reset\r\n");
      }
      resetCause->reason = BOOTLOADER_RESET_REASON_PANEL_DO;
      resetCause->signature = BOOTLOADER_RESET_SIGNATURE_VALID;
      NVIC_SystemReset();
  }else if(reset_mode == XMODEM_RESET){
      if(hub_log_enable){
          DS_app_log_error("XMODEM reset\r\n");
      }
      resetCause->reason = BOOTLOADER_RESET_REASON_PANEL_XMODEM;
      resetCause->signature = BOOTLOADER_RESET_SIGNATURE_VALID;
      NVIC_SystemReset();
  }else{

  }
}

int analysis_panel_bc_pkt(const unsigned char *bc_pkt, int bc_pkt_len,
                          unsigned char *result_pkt, int *result_pkt_len)
{
  int iret = 0;
  unsigned char i, j, pkt_len;
  i = j = pkt_len  = 0;
  unsigned char switch_io_num = 0;
  unsigned char updateme_io_num = 0;
  unsigned char key;
  unsigned char ioen_value[16] = {0x00};
  unsigned char ioen_flag = 0;
  unsigned char sounder_value[15] = {0x00};
  unsigned char sounder_flag = 0;
  unsigned char keypad_value[10] = {0x00};
  unsigned char keypad_flag = 0;
  unsigned char switch_value[26] = {0x00};  //SWITCH_BC_ID_CN 12*2+2
  unsigned char switch_flag = 0;
  unsigned char updateme_value[14] = {0x00};  //UPDATEME_BC_ID_CN 12+2
  unsigned char updateme_flag = 0;

  while((i + 1) < bc_pkt_len){
      key = bc_pkt[i];
      if(key == BC_IOEN_BTYPE){
          for(j = 0; (j < sizeof(ioen_value)) && ((i+1+j) < bc_pkt_len); j++){
              ioen_value[j] = bc_pkt[i+1+j];
          }
          if(j == sizeof(ioen_value)){
              ioen_flag = 1;
          }else{
              return 1;
          }
          i = i + sizeof(ioen_value) + 1;
      }else if(key == BC_SOUNDER_BTYPE){
          for(j = 0; (j < sizeof(sounder_value)) && ((i+1+j) < bc_pkt_len); j++){
              sounder_value[j] = bc_pkt[i+1+j];
          }
          if(j == sizeof(sounder_value)){
              sounder_flag = 1;
          }else{
              return 1;
          }
          i = i + sizeof(sounder_value) + 1;
      }else if(key == BC_KEYPAD_BTYPE){
          for(j = 0; (j < sizeof(keypad_value)) && ((i+1+j) < bc_pkt_len); j++){
              keypad_value[j] = bc_pkt[i+1+j];
          }
          if(j == sizeof(keypad_value)){
              keypad_flag = 1;
          }else{
              return 1;
          }
          i = i + sizeof(keypad_value) + 1;
      }else if(key == BC_SWITCH_BTYPE){
          switch_io_num = (bc_pkt[i+2] / 2);
          if(switch_io_num == 0 || switch_io_num > SWITCH_BC_ID_CN){
              return 1;
          }
          for(j = 0; (j < (2 + switch_io_num * 2)) && ((i+1+j) < bc_pkt_len); j++){
              switch_value[j] = bc_pkt[i+1+j];
          }
          if(j == (2 + switch_io_num * 2)){
              switch_flag = 1;
          }else{
              return 1;
          }
          i = i + (2 + switch_io_num * 2) + 1;
      }else if(key == BC_UPDATEME_BTYPE){
          updateme_io_num = (bc_pkt[i+1] - 1);
          if(updateme_io_num == 0 || updateme_io_num > UPDATEME_BC_ID_CN){
              return 1;
          }
          for(j = 0; (j < (2 + updateme_io_num)) && ((i+1+j) < bc_pkt_len); j++){
              updateme_value[j] = bc_pkt[i+1+j];
          }
          if(j == (2 + updateme_io_num)){
              updateme_flag = 1;
          }else{
              return 1;
          }
          i = i + (2 + updateme_io_num) + 1;
      }else{
          i = i + (1 +  bc_pkt[i+1]) + 1;
      }
  }

  if(ioen_flag){
      result_pkt[pkt_len++] = BC_IOEN_BTYPE;
      memcpy(&result_pkt[pkt_len], ioen_value, sizeof(ioen_value));
      pkt_len += sizeof(ioen_value);
      if(hub_log_enable){
          DS_app_log_hexdump_error("[IOEN]",ioen_value,sizeof(ioen_value));
      }
  }
  if(sounder_flag){
      result_pkt[pkt_len++] = BC_SOUNDER_BTYPE;
      memcpy(&result_pkt[pkt_len], sounder_value, sizeof(sounder_value));
      pkt_len += sizeof(sounder_value);
      if(hub_log_enable){
          DS_app_log_hexdump_error("[SOUNDER]",sounder_value,sizeof(sounder_value));
      }
  }
  if(keypad_flag){
      result_pkt[pkt_len++] = BC_KEYPAD_BTYPE;
      memcpy(&result_pkt[pkt_len], keypad_value, sizeof(keypad_value));
      pkt_len += sizeof(keypad_value);
      if(hub_log_enable){
          DS_app_log_hexdump_error("[KEYPAD]",keypad_value,sizeof(keypad_value));
      }
  }
  if(switch_flag){
      result_pkt[pkt_len++] = BC_SWITCH_BTYPE;
      memcpy(&result_pkt[pkt_len], switch_value, (2 + switch_io_num * 2));
      pkt_len += (2 + switch_io_num * 2);
      if(hub_log_enable){
          DS_app_log_hexdump_error("[SWITCH]",switch_value, (2 + switch_io_num * 2));
      }
  }
  if(updateme_flag){
      result_pkt[pkt_len++] = BC_UPDATEME_BTYPE;
      memcpy(&result_pkt[pkt_len], updateme_value, (2 + updateme_io_num));
      pkt_len += (2 + updateme_io_num);
      if(hub_log_enable){
          DS_app_log_hexdump_error("[UPDATEME]",updateme_value, (2 + updateme_io_num));
      }
  }

  *result_pkt_len = pkt_len;
  if(*result_pkt_len){
      if(hub_log_enable){
          DS_app_log_hexdump_error("[result]",result_pkt,*result_pkt_len);
      }
  }else{
      if(hub_log_enable){
          DS_app_log_error("[result]:N\r\n");
      }
  }

  return iret;
}

int analysis_panel_p2p_pkt(const unsigned char *p2p_pkt, int p2p_pkt_len,
                           unsigned char *result_pkt, int *result_pkt_len,
                           unsigned char rfmid)
{
  int i, j, pkt_len;
  i = j = pkt_len = 0;
  unsigned char key;
  unsigned char led_ctrl[LEDCTRL_LENGTH] = {0x00};
  unsigned char led_ctrl_flag = 0;
  unsigned char key_value = 0;
  unsigned char key_value_flag = 0;
  unsigned char operate_ctrl[OPERATECTRL_LENGTH] = {0};
  unsigned char operate_flag = 0;
  unsigned char option_ctrl[OPTION_LENGTH] = {0};
  unsigned char option_flag = 0;
  while((i + 1) < p2p_pkt_len){
      key = p2p_pkt[i];
      if(key == COMLED_CTRL_KEY){
          for(j = 0; (j < 5) && ((i+1+j) < p2p_pkt_len); j++){  //不再使用LEDCTRL_LENGTH
              led_ctrl[j+1] = p2p_pkt[i+1+j];
          }
          if(j == 5){  //不再使用LEDCTRL_LENGTH
              led_ctrl_flag = 1;
          }else{
              return 1;
          }
          i = i + 5 + 1;
      }else if(key == KEYVALUE_GET_KEY){
          for(j = 0; (j < 1) && ((i+1+j) < p2p_pkt_len); j++){
              key_value = p2p_pkt[i+1];
          }
          if(j == 1){
              key_value_flag = 1;
          }else{
              return 1;
          }
          i = i + 2;
      }else if(key == OPERATE_CTRL_KEY){
          for(j = 0; (j < 3) && ((i+1+j) < p2p_pkt_len); j++){ //不再使用OPERATECTRL_LENGTH
              operate_ctrl[j+1] = p2p_pkt[i+1+j];
          }
          if(j == 3){
              operate_flag = 1;
          }else{
              return 1;
          }
          i = i + 3 + 1;
      }else if(key == OPTION_KEY){
          for(j = 0; (j < OPTION_LENGTH) && ((i+1+j) < p2p_pkt_len); j++){
              option_ctrl[j] = p2p_pkt[i+1+j];
          }
          if(j == OPTION_LENGTH){
              option_flag = 1;
          }else{
              return 1;
          }
          i = i + OPTION_LENGTH + 1;
      }else{
          i = i + (1 +  p2p_pkt[i+1]) + 1;
      }
  }

  if(option_flag){
      result_pkt[pkt_len++] = OPTION_KEY;
      memcpy(&result_pkt[pkt_len], option_ctrl, OPTION_LENGTH);
      pkt_len += OPTION_LENGTH;
      setDeviceParam(rfmid, ENpbyNodeOptionFirst, option_ctrl); //p2p option保存从net层移到了HUB API
      if(hub_log_enable){
          DS_app_log_hexdump_error("[option_ctrl]",option_ctrl,OPTION_LENGTH);
      }
  }
  if(operate_flag){
      result_pkt[pkt_len++] = OPERATE_CTRL_KEY;
      updata_node_aseq(ASEQ_OPERATE, rfmid);
      operate_ctrl[0] = get_node_aseq(ASEQ_OPERATE, rfmid);
      memcpy(&result_pkt[pkt_len], operate_ctrl, OPERATECTRL_LENGTH);
      pkt_len += OPERATECTRL_LENGTH;
      if(hub_log_enable){
          DS_app_log_hexdump_error("[operate_ctrl]",operate_ctrl,OPERATECTRL_LENGTH);
      }
  }
  if(led_ctrl_flag){
      result_pkt[pkt_len++] = COMLED_CTRL_KEY;
      updata_node_aseq(ASEQ_LED, rfmid);
      led_ctrl[0] = get_node_aseq(ASEQ_LED, rfmid);
      memcpy(&result_pkt[pkt_len], led_ctrl, LEDCTRL_LENGTH);
      pkt_len += LEDCTRL_LENGTH;
      if(hub_log_enable){
          DS_app_log_hexdump_error("[led_ctrl]",led_ctrl,LEDCTRL_LENGTH);
      }
  }
  if(key_value_flag){
      result_pkt[pkt_len++] = KEYVALUE_GET_KEY;
      result_pkt[pkt_len++] = key_value;
  }

  *result_pkt_len = pkt_len;
  if(*result_pkt_len){
      if(hub_log_enable){
          DS_app_log_hexdump_error("[result]",result_pkt,*result_pkt_len);
      }
  }else{
      if(hub_log_enable){
          DS_app_log_error("[result]:N\r\n");
      }
  }
  return 0;
}

int analysis_rfm_evt_payload_keyvalue(const unsigned char *payload, int payload_len,
                          unsigned char *result_msg, int *result_msg_len,
                          unsigned char rfmid)
{
  int msg_len = 0;
  int payload_idx = 0;
  unsigned char kv_len = 0;
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
  int i = 0;
  in_output_flag = 0;
  temp_humi_flag = 0;
  volt_c_power_flag = 0;
  run_energy_flag = 0;
  key_press_flag = 0;
  key_multi_press_flag = 0;
  key_multi_press_num = 0;
#endif

  while(payload_idx < payload_len){
      if(payload[payload_idx] == 0x10){
          kv_len = 3;
          if((payload_idx + kv_len) > payload_len){
              break;
          }
          memcpy((char *)(result_msg + msg_len), (payload + payload_idx), kv_len); //key[1]+value[2]
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
          for(i = 0; i < 2; i++){
              in_output[i] = payload[payload_idx + 1 + i];
          }
          in_output_flag = 1;
#endif
          msg_len += kv_len;
          payload_idx += kv_len;
      }else if(payload[payload_idx] == 0x12){
          kv_len = 5;
          if((payload_idx + kv_len) > payload_len){
              break;
          }
          memcpy((char *)(result_msg + msg_len), (payload + payload_idx), kv_len); //key[1]+value[4]
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
          for(i = 0; i < 4; i++){
              temp_humi[i] = payload[payload_idx + 1 + i];
          }
          temp_humi_flag = 1;
#endif
          msg_len += kv_len;
          payload_idx += kv_len;
      }else if(payload[payload_idx] == 0x13){
          kv_len = 6;
          if((payload_idx + kv_len) > payload_len){
              break;
          }
          memcpy((char *)(result_msg + msg_len), (payload + payload_idx), kv_len); //key[1]+value[5]
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
          for(i = 0; i < 5; i++){
              volt_c_power[i] = payload[payload_idx + 1 + i];
          }
          volt_c_power_flag = 1;
#endif
          msg_len += kv_len;
          payload_idx += kv_len;
      }else if(payload[payload_idx] == 0x14){
          kv_len = 9;
          if((payload_idx + kv_len) > payload_len){
              break;
          }
          memcpy((char *)(result_msg + msg_len), (payload + payload_idx), kv_len); //key[1]+value[8]
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
          for(i = 0; i < 8; i++){
              run_energy[i] = payload[payload_idx + 1 + i];
          }
          run_energy_flag = 1;
#endif
          msg_len += kv_len;
          payload_idx += kv_len;
      }else if(payload[payload_idx] == 0x2e){
          kv_len = 5;
          if((payload_idx + kv_len) > payload_len){
              break;
          }
          memcpy((char *)(result_msg + msg_len), (payload + payload_idx), kv_len); //key[1]+value[4]
          msg_len += kv_len;
          payload_idx += kv_len;
      }else if(payload[payload_idx] == 0x2f){
          kv_len = payload[payload_idx + 1] + 2;
          if((payload_idx + kv_len) > payload_len){
              break;
          }
          memcpy((char *)(result_msg + msg_len), (payload + payload_idx), kv_len); //key[1]+value[N]
          msg_len += kv_len;
          payload_idx += kv_len;
      }else if(payload[payload_idx] == 0x30){
          kv_len = 2;
          if((payload_idx + kv_len) > payload_len){
              break;
          }
          memcpy((char *)(result_msg + msg_len), (payload + payload_idx), kv_len); //key[1]+value[1]
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
          key_press[0] = payload[payload_idx + 1];
          key_press_flag = 1;
#endif
          msg_len += kv_len;
          payload_idx += kv_len;
      }else if(payload[payload_idx] == 0x31){
          kv_len = payload[payload_idx + 1] + 2;
          if((payload_idx + kv_len) > payload_len){
              break;
          }
          memcpy((char *)(result_msg + msg_len), (payload + payload_idx), kv_len); //key[1]+value[N]
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
          key_multi_press_num = payload[payload_idx + 1];
          if(key_multi_press_num > 32){
              key_multi_press_num = 32;
          }
          for(i = 0; i < key_multi_press_num; i++){
              key_multi_press[i] = payload[payload_idx + 2 + i];
          }
          key_multi_press_flag = 1;
#endif
          msg_len += kv_len;
          payload_idx += kv_len;
      }else if(payload[payload_idx] == APP_KEY_VALUE_ID_OPTION){
          kv_len = 4;
          if((payload_idx + kv_len) > payload_len){
              break;
          }
          setDeviceParam(rfmid, ENpbyNodeOptionFirst, (unsigned char *)&payload[payload_idx + 1]); //更新子设备的option
          memcpy((char *)(result_msg + msg_len), (payload + payload_idx), kv_len); //key[1]+value[3]
          msg_len += kv_len;
          payload_idx += kv_len;
      }else if(payload[payload_idx] == APP_KEY_VALUE_ID_FILE_CHECK_RET){ //0xfb
          kv_len = payload[payload_idx + 1] + 2;
#ifdef HUB_DEVICE
          production_deal_check_result_keyvalue(rfmid,
                                                (unsigned char *)&payload[payload_idx + 1], (payload[payload_idx + 1] + 1));
#endif
          payload_idx += kv_len;
      }else if(payload[payload_idx] == APP_KEY_VALUE_ID_FILE_TRANS_CONFIRM){ //0xfd
          kv_len = payload[payload_idx + 1] + 2;
#ifdef HUB_DEVICE
          production_deal_transport_confirm_keyvalue(rfmid,
                                                     (unsigned char *)&payload[payload_idx + 1], (payload[payload_idx + 1] + 1));
#endif
          payload_idx += kv_len;
      }else if(payload[payload_idx] == APP_KEY_VALUE_ID_FILE_TRANS_REQ){ //0xff
          kv_len = payload[payload_idx + 1] + 2;
#ifdef HUB_DEVICE
          production_deal_transport_request_keyvalue(rfmid,
                                                     (unsigned char *)&payload[payload_idx + 1], (payload[payload_idx + 1] + 1));
#endif
          payload_idx += kv_len;
      }else{
          if(payload[payload_idx + 1] == 0){
              break;
          }
          //len 大于 payload里keyvalue的最大的长度 cmd(4,5): 10+KEY+(LEN+DATA) = HUB_API_USART_MSG_DATA_MAX_LEN -13
          if(payload[payload_idx + 1] > (HUB_API_USART_MSG_DATA_MAX_LEN - 25)){
              break;
          }
          kv_len = payload[payload_idx + 1] + 2;
          if((payload_idx + kv_len) > payload_len){
              break;
          }
          memcpy((char *)(result_msg + msg_len), (payload + payload_idx), kv_len); //key[1]+value[N]
          msg_len += kv_len;
          payload_idx += kv_len;
      }
  }
  if(msg_len == 0 || msg_len > payload_len){ //过滤之后不可能比原始的长度还长
      return 1;
  }
  *result_msg_len = msg_len;
  return 0;
}

void printf_pkt(const hub_api_usart_msg_t *ptr_pkt)
{
  (void)ptr_pkt;
#if(0)
  int i = 0;
  DS_app_log_debug("ptr_pkt->stx %02x\r\n",ptr_pkt->stx);
  DS_app_log_debug("ptr_pkt->seq %02x\r\n",ptr_pkt->seq);
  DS_app_log_debug("ptr_pkt->len %02x\r\n",ptr_pkt->len);
  DS_app_log_debug("ptr_pkt->statu %02x\r\n",ptr_pkt->statu);
  DS_app_log_debug("ptr_pkt->fcode %02x\r\n",ptr_pkt->fcode);
  DS_app_log_debug("ptr_pkt->data:\r\n");
  for(i = 0; i < ptr_pkt->len - HUB_API_USART_MSG_LEN_MIN_VALUE; i++){
      DS_app_log_debug("%02x ",ptr_pkt->data.data[i]);
  }
  DS_app_log_debug("\r\n");
  DS_app_log_debug("ptr_pkt->crc[0] %02x\r\n",ptr_pkt->crc[0]);
  DS_app_log_debug("ptr_pkt->crc[1] %02x\r\n",ptr_pkt->crc[1]);
  DS_app_log_debug("ptr_pkt->etx %02x\r\n",ptr_pkt->etx);
#endif
}

static MultiTimer wait_ack_Timer = {.Handle = 0x01};
static MultiTimer usart_idle_Timer = {.Handle = 0x02};
static MultiTimer avg_rssi_Timer = {.Handle = 0x03};
static MultiTimer delay_com_tx_task_Timer = {.Handle = 0x04};
static MultiTimer fix_10s_Timer = {.Handle = 0x05};
static MultiTimer clean_busy_Timer = {.Handle = 0x06};

static void wait_ack_TimerCallback(MultiTimer* timer, void *userData)
{
  (void)timer;
  bool timeout = true;
  if(userData){
      memcpy(userData, &timeout, 1);
  }
}

void start_wait_ack_Timer(int time, void *userData)
{
  bool timeout = false;
  if(userData){
      memcpy(userData, &timeout, 1);
  }
  softwareMultiTimerStart(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &wait_ack_Timer, time, wait_ack_TimerCallback, userData, 0);
}

void stop_wait_ack_Timer(void *userData)
{
  bool timeout = false;
  if(userData){
      memcpy(userData, &timeout, 1);
  }
  softwareMultiTimerStop(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &wait_ack_Timer, 0);
}

static void usart_idle_TimerCallback(MultiTimer* timer, void *userData)
{
  (void)timer;
  (void)userData;
  extern void DS_hub_api_usart_msg_parse_init(void);
  DS_hub_api_usart_msg_parse_init();
}

void start_usart_idle_Timer(int time, void *userData)
{
  (void)userData;
  softwareMultiTimerStart(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &usart_idle_Timer, time, usart_idle_TimerCallback, userData, 0);
}

void stop_usart_idle_Timer(void *userData)
{
  (void)userData;
  softwareMultiTimerStop(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &usart_idle_Timer, 0);
}

void restart_usart_idle_Timer(int time, void *userData)
{
  if(softwareMultiTimerFind(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &usart_idle_Timer) >= 0){
      stop_usart_idle_Timer(userData);
  }
  start_usart_idle_Timer(time, userData);
}

static void avg_rssi_TimerCallback(MultiTimer* timer, void *userData)
{
  (void)timer;
  (void)userData;
  signed char rssi = getCurrentBackRssi();
  DS_hub_avg_rssi(rssi);
  start_avg_rssi_Timer(timer->Time, NULL);
}

void start_avg_rssi_Timer(int time, void *userData)
{
  (void)userData;
  softwareMultiTimerStart(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &avg_rssi_Timer, time, avg_rssi_TimerCallback, userData, 0);
}

static void delay_com_tx_task_TimerCallback(MultiTimer* timer, void *userData)
{
  (void)timer;
  (void)userData;
  unsigned char delay_txtask = 0;
  setThisParam(ENbyDelayTxTask, &delay_txtask);
}

void start_delay_com_tx_task(int time, void *userData)
{
  (void)userData;
  softwareMultiTimerStart(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &delay_com_tx_task_Timer, time, delay_com_tx_task_TimerCallback, userData, 0);
}

static void fix_10s_TimerCallback(MultiTimer* timer, void *userData)
{
  (void)timer;
  (void)userData;
  unsigned char IOen_lock;
  int i = 0;
  for(i = 0; i < NODE_MAX_COUNT; i++){
      if(i < DEVICE_TYPE_IO_CN){
          getDeviceParam(i+1, ENbyIOenLock, &IOen_lock);
          if(IOen_lock){
              IOen_lock--;
              setDeviceParam(i+1, ENbyIOenLock, &IOen_lock);
          }
      }
      update_rfm_offline_countdown(i);
      update_rfm_qrfh_countdown(i);
  }
  start_fix_10S_Timer(timer->Time, userData);
}

void start_fix_10S_Timer(int time, void *userData)
{
  (void)userData;
  softwareMultiTimerStart(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &fix_10s_Timer, time, fix_10s_TimerCallback, userData, 0);
}

static void clean_busy_Callback(MultiTimer* timer, void *userData)
{
  (void)timer;
  (void)userData;
  unsigned char bcast_busy = 0;
  setThisParam(ENbyBcastBusy, (unsigned char *)&bcast_busy);
}

void start_clean_bc_busy_Timer(int time, void *userData)
{
  softwareMultiTimerStop(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &clean_busy_Timer, 0);
  softwareMultiTimerStart(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &clean_busy_Timer, time, clean_busy_Callback, userData, 0);
}

unsigned char get_month_from_str(char * month)
{
  unsigned char m;
  if(memcmp(month, "Jan", 3) == 0){
      m = 1;
  }else if(memcmp(month, "Feb", 3) == 0){
      m = 2;
  }else if(memcmp(month, "Mar", 3) == 0){
      m = 3;
  }else if(memcmp(month, "Apr", 3) == 0){
      m = 4;
  }else if(memcmp(month, "May", 3) == 0){
      m = 5;
  }else if(memcmp(month, "Jun", 3) == 0){
      m = 6;
  }else if(memcmp(month, "Jul", 3) == 0){
      m = 7;
  }else if(memcmp(month, "Aug", 3) == 0){
      m = 8;
  }else if(memcmp(month, "Sep", 3) == 0){
      m = 9;
  }else if(memcmp(month, "Oct", 3) == 0){
      m = 10;
  }else if(memcmp(month, "Nov", 3) == 0){
      m = 11;
  }else if(memcmp(month, "Dec", 3) == 0){
      m = 12;
  }else{
      m = 0xff;
  }
  return m;
}

unsigned short reset_getResetReason(void)
{
  BootloaderResetCause_t* cause = (BootloaderResetCause_t*) (SRAM_BASE);
  return cause->reason;
}

static unsigned char offline_countdown[NODE_MAX_COUNT] ={0x00};

void set_rfm_offline_countdown(unsigned char rfmid)
{
  if(rfmid == 0 || rfmid == 0xff ){
      return;
  }
#if(0)
  if(!check_rfmid_is_registered(rfmid)){
      return;
  }
#endif
  offline_countdown[rfmid] = MAX_OFFLINE_COUNTDOWN;
}

void set_rfm_offline(unsigned char rfmid)
{
  if(rfmid == 0 || rfmid == 0xff ){
      return;
  }
  offline_countdown[rfmid] = 0;
}

unsigned char get_rfm_offline_countdown(unsigned char rfmid)
{
  if(rfmid == 0 || rfmid == 0xff ){
      return 0;
  }
  return offline_countdown[rfmid];
}

void update_rfm_offline_countdown(unsigned char rfmid)
{
  if(rfmid == 0 || rfmid == 0xff ){
      return;
  }
#if(0)
  if(!check_rfmid_is_registered(rfmid)){
      offline_countdown[rfmid] = 0;
      return;
  }
#endif
  if(offline_countdown[rfmid]){
      offline_countdown[rfmid]--;
  }
}

bool check_rfm_is_offline(unsigned char rfmid)
{
  if(rfmid == 0 || rfmid == 0xff){
      return true;
  }
#if(0)
  if(!check_rfmid_is_registered(rfmid)){
      return true;
  }
#endif
  if(offline_countdown[rfmid]){
      return false;
  }
  return true;
}

#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
static int print_preallocated(cJSON *root)
{
    /* declarations */
    char *out = NULL;
    char *buf = NULL;
    char *buf_fail = NULL;
    size_t len = 0;
    size_t len_fail = 0;

    /* formatted print */
    out = cJSON_Print(root);

    /* create buffer to succeed */
    /* the extra 5 bytes are because of inaccuracies when reserving memory */
    len = strlen(out) + 5;
    buf = (char*)sl_malloc(len);
    if (buf == NULL)
    {
        exit(1);
    }

    /* create buffer to fail */
    len_fail = strlen(out);
    buf_fail = (char*)sl_malloc(len_fail);
    if (buf_fail == NULL)
    {
        printf("Failed to allocate memory.\n");
        exit(1);
    }

    /* Print to buffer */
    if (!cJSON_PrintPreallocated(root, buf, (int)len, 1)) {
        printf("cJSON_PrintPreallocated failed!\n");
        if (strcmp(out, buf) != 0) {
            printf("cJSON_PrintPreallocated not the same as cJSON_Print!\n");
            printf("cJSON_Print result:\n%s\n", out);
            printf("cJSON_PrintPreallocated result:\n%s\n", buf);
        }
        sl_free(out);
        sl_free(buf_fail);
        sl_free(buf);
        return -1;
    }

    /* success */
    printf("%s\n", buf);

    /* force it to fail */
    if (cJSON_PrintPreallocated(root, buf_fail, (int)len_fail, 1)) {
        printf("cJSON_PrintPreallocated failed to show error with insufficient memory!\n");
        printf("cJSON_Print result:\n%s\n", out);
        printf("cJSON_PrintPreallocated result:\n%s\n", buf_fail);
        sl_free(out);
        sl_free(buf_fail);
        sl_free(buf);
        return -1;
    }

    sl_free(out);
    sl_free(buf_fail);
    sl_free(buf);
    return 0;
}
#endif

void creat_rfm_add_cjson(unsigned char rfmid, unsigned char type,
                         signed char rssi, unsigned char battv,
                         unsigned char temp, unsigned char *ver)
{
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
  cJSON *root = NULL;
  char mac_str[25] = {0x00};
  char mac[MAC_ADDRESS_LENGTH] = {0x00};
  char app_ver[13] = {0x00};
  char rf_ver[13] = {0x00};
  root = cJSON_CreateObject();
  if(!root){
      return;
  }

  getNodeJoinMac((uint8_t *)mac, rfmid);
  sprintf(mac_str,"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",mac[0],mac[1],mac[2],
          mac[3],mac[4],mac[5],mac[6],mac[7]);
  cJSON_AddItemToObject(root, "RID", cJSON_CreateNumber(rfmid));
  cJSON_AddItemToObject(root, "DT", cJSON_CreateNumber(type));
  cJSON_AddItemToObject(root, "MAC", cJSON_CreateString((char *)mac_str));
  cJSON_AddItemToObject(root, "CMD", cJSON_CreateString((char *)"ADD"));

  cJSON_AddNumberToObject(root, "BT", battv);
  if(((ver[0] << 16)+(ver[1] << 8)+(ver[2])) <= 0x010000){
      cJSON_AddNumberToObject(root, "RSSI", rssi + 128);
  }else{
      cJSON_AddNumberToObject(root, "RSSI", rssi);
  }
  cJSON_AddNumberToObject(root, "TP", temp);

  sprintf(rf_ver,"%d.%d.%d",ver[0],ver[1],ver[2]);
  cJSON_AddItemToObject(root, "RFVER", cJSON_CreateString((char *)rf_ver));
  sprintf(app_ver,"%d.%d.%d",ver[3],ver[4],ver[5]);
  cJSON_AddItemToObject(root, "APPVER", cJSON_CreateString((char *)app_ver));
  APP_PRINTF("deviceAddHead\r\n");
  if(print_preallocated(root) != 0) {
      cJSON_Delete(root);
  }
  APP_PRINTF("deviceAddTail\r\n");
  cJSON_Delete(root);
#else
  (void)rfmid;
  (void)type;
  (void)rssi;
  (void)battv;
  (void)temp;
  (void)ver;
#endif
}

void creat_rfm_report_cjson(unsigned char rfmid, unsigned char type,
                            signed char rssi, unsigned char battv,
                            unsigned char temp)
{
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
  cJSON *root = NULL;
  cJSON *message = NULL;
  cJSON *ptr_inoutput = NULL;
  cJSON *ptr_temphumi = NULL;
  cJSON *ptr_voltcpower = NULL;
  cJSON *ptr_runenergy = NULL;
  cJSON *ptr_keypress = NULL;
  cJSON *ptr_keymultipress = NULL;

  char mac_str[25] = {0x00};
  char mac[MAC_ADDRESS_LENGTH] = {0x00};

  if(!in_output_flag && !temp_humi_flag && !volt_c_power_flag &&
      !run_energy_flag && !key_press_flag && !key_multi_press_flag){
      return;
  }

  root = cJSON_CreateObject();
  if(!root){
      return;
  }
  DS_app_func_tm_in();
  getNodeJoinMac((uint8_t *)mac, rfmid);
  sprintf(mac_str,"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",mac[0],mac[1],mac[2],
          mac[3],mac[4],mac[5],mac[6],mac[7]);
  cJSON_AddItemToObject(root, "RID", cJSON_CreateNumber(rfmid));
  cJSON_AddItemToObject(root, "DT", cJSON_CreateNumber(type));
  cJSON_AddItemToObject(root, "MAC", cJSON_CreateString((char *)mac_str));
  cJSON_AddItemToObject(root, "CMD", cJSON_CreateString((char *)"REPORT"));

  cJSON_AddNumberToObject(root, "BT", battv);
  cJSON_AddNumberToObject(root, "RSSI", rssi);
  cJSON_AddNumberToObject(root, "TP", temp);

  cJSON_AddItemToObject(root, "KV", message = cJSON_CreateObject());
#if(0)
  in_output_flag = 1;
  in_output[0] = 1;
  in_output[1] = 2;
  temp_humi_flag = 1;
  temp_humi[0] = 3;
  temp_humi[1] = 4;
  temp_humi[2] = 5;
  temp_humi[3] = 6;
  volt_c_power_flag = 1;
  volt_c_power[0] = 7;
  volt_c_power[1] = 8;
  volt_c_power[2] = 9;
  volt_c_power[3] = 10;
  volt_c_power[4] = 11;
  run_energy_flag = 1;
  run_energy[0] = 12;
  run_energy[1] = 13;
  run_energy[2] = 14;
  run_energy[3] = 15;
  run_energy[4] = 16;
  run_energy[5] = 17;
  run_energy[6] = 18;
  run_energy[7] = 19;
  key_press_flag = 1;
  key_press[0] = 20;
  key_multi_press_flag = 1;
  key_multi_press_num = 7;
  key_multi_press[0] = 21;
  key_multi_press[1] = 22;
  key_multi_press[2] = 23;
  key_multi_press[3] = 24;
  key_multi_press[4] = 25;
  key_multi_press[5] = 26;
  key_multi_press[6] = 27;
#endif
  if(in_output_flag){
      ptr_inoutput = cJSON_CreateIntArray(in_output, 2);
      cJSON_AddItemToObject(message, "IN/OUTPUT", ptr_inoutput);
  }
  if(temp_humi_flag){
      ptr_temphumi = cJSON_CreateIntArray(temp_humi, 4);
      cJSON_AddItemToObject(message, "TempHumi", ptr_temphumi);
  }
  if(volt_c_power_flag){
      ptr_voltcpower = cJSON_CreateIntArray(volt_c_power, 5);
      cJSON_AddItemToObject(message, "VoltCPower", ptr_voltcpower);
  }
  if(run_energy_flag){
      ptr_runenergy = cJSON_CreateIntArray(run_energy, 8);
      cJSON_AddItemToObject(message, "RunTimeEnergy", ptr_runenergy);
  }
  if(key_press_flag){
      ptr_keypress  = cJSON_CreateIntArray(key_press, 1);
      cJSON_AddItemToObject(message, "KeyPress", ptr_keypress);
  }
  if(key_multi_press_flag){
      ptr_keymultipress = cJSON_CreateIntArray(key_multi_press, key_multi_press_num);
      cJSON_AddItemToObject(message, "KeyMultiPress", ptr_keymultipress);
  }
  APP_PRINTF("deviceReportHead\r\n");
  if(print_preallocated(root) != 0) {
      cJSON_Delete(root);
  }
  APP_PRINTF("deviceReportTail\r\n");
  cJSON_Delete(root);
  DS_app_func_tm_end("report");
#else
  (void)rfmid;
  (void)type;
  (void)rssi;
  (void)battv;
  (void)temp;
#endif
}

#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
void set_bc_delete(bool is_lock)
{
  bc_delete = is_lock;
}

bool get_bc_delete(void)
{
  return bc_delete;
}

void set_can_delete(bool is_can)
{
  can_delete = is_can;
}

bool get_can_delete(void)
{
  return can_delete;
}

void set_delete_rfmid(unsigned char rfmid)
{
  delete_rfmid = rfmid;
}

unsigned char get_delete_rfmid(void)
{
  return delete_rfmid;
}

static void delete_rfm_TimerCallback(MultiTimer* timer, void *userData)
{
  (void)timer;
  (void)userData;
  set_can_delete(true);
}

void start_delete_rfm_timer(int time, void *userData)
{
  (void)userData;
  set_bc_delete(true);
  softwareMultiTimerStart(EN_LP_HARD_TIMER_EM3_SYS_RTC_1, &delet_rfm_Timer, time, delete_rfm_TimerCallback, userData, 0);
}

#endif

void hub_delete_rfm(unsigned char rfmid)
{
#ifndef CONFIG_NVM_VERSION
  unsigned char mac_addr[MAC_ADDRESS_LENGTH] = {0}; //删MAC地址
  unsigned char sn[SN_LENGTH] = {0}; //删SN
  unsigned char devicetype[3] = {0};
  unsigned char codeAB[KEY_MAX_LENGTH] = {0};
#endif
  unsigned char info[NODE_JOIN_INFO_LENGTH] = {0};  //删注册状态
  unsigned char option[OPTION_LENGTH] = {0};//删option
#ifndef CONFIG_NVM_VERSION
  unsigned char qrfh1 = 0;
  unsigned char qrfh2 = 0;
#endif
  unsigned char qrfr1 = 0;
  unsigned char qrfr2 = 0;
  unsigned char groupix = 0;
  unsigned char rollcode[ROLLING_CODE_LENGTH] = {0x00,0x00,0x00,0x00};
  unsigned char flag = 0;
  unsigned char led_ctrl[LEDCTRL_LENGTH] = {0};
  unsigned char operate_ctrl[OPERATECTRL_LENGTH] = {0};
  unsigned char keyvalue_get[GETKEYVALUE_LENGTH] = {0};
  unsigned char idx = 0;
  unsigned char bit = 0;
#ifdef CONFIG_NVM_VERSION
#ifdef HUB_DEVICE
  uint8_t nodeRegInfo[NODEREGINFO_MAX_LEN]={0};
  uint8_t qrfh12[NodeQrfH12Group_MAX_LEN]={0};
#endif
#endif

  APP_PRINTF("now delete %02x",rfmid);
  //删除rfmid设备
  getThisParam(ENbyNodeJoinInfo, (unsigned char *)info);
  idx = (rfmid - 1)/8;
  bit = (rfmid - 1)%8;
  HUB_API_CLEAN_BIT(info[idx], bit);
  setThisParam(ENbyNodeJoinInfo, (unsigned char *)info);
#ifdef CONFIG_NVM_VERSION
#ifdef HUB_DEVICE
  setNodeRegInfoPack(rfmid,nodeRegInfo);
  setNodeQrfH12Group(rfmid,qrfh12);
  clean_device_ram_qrfh(rfmid); //这里删ram里的qrfh
#endif
#else
  setNodeJoinMac(mac_addr, rfmid);
  setNodeJoinCodeAB(codeAB, rfmid);
  setDeviceParam(rfmid, ENpbyNodeSNFirst, sn);
  setDeviceParam(rfmid, ENpbyNodeQrfH1First, &qrfh1);
  setDeviceParam(rfmid, ENpbyNodeQrfH2First, &qrfh2);
  setDeviceParam(rfmid, ENpbyNodeDeviceTypeFirst, devicetype);
#endif
  setDeviceParam(rfmid, ENpbyNodeOptionFirst, option); //删ram和nvm里的option
  setDeviceParam(rfmid, ENpbyNodeQrfR1First, &qrfr1);
  setDeviceParam(rfmid, ENpbyNodeQrfR2First, &qrfr2);
  setDeviceParam(rfmid, ENpbyNodeGroupIdxFirst, &groupix);
  setDeviceParam(rfmid, HubRecvRollingCodeFirst, rollcode);
  setDeviceParam(rfmid, ENbyLedCtrlFlag, &flag);
  setDeviceParam(rfmid, ENbyOperateCtrlFlag, &flag);
  setDeviceParam(rfmid, ENbyKeyValueGetFlag, &flag);
  setDeviceParam(rfmid, ENbyLedCtrl, led_ctrl);
  setDeviceParam(rfmid, ENbyOperateCtrl, operate_ctrl);
  setDeviceParam(rfmid, ENbyKeyValueGet, keyvalue_get);
  set_rfm_offline(rfmid);
}

void hub_delay_delete_rfm(void)
{
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE)
  if(get_can_delete() == false){
      return;
  }
  unsigned char rfmid = get_delete_rfmid();
  hub_delete_rfm(rfmid);

  getAllNodeJoinMac();

  set_can_delete(false);
  set_bc_delete(false);
#endif
}

void hub_api_test(void)
{
#if(0)
  short data = 0x1122;
  unsigned char *p;
  p = (unsigned char *)&data;
  if(*p == 0x22){
      app_log_info("short model\r\n");
  }else if(*p == 0x11){
      app_log_info("big model\r\n");
  }
  app_log_info("%s\r\n",FILE_NAME(__FILE__));
  app_log_info("%s\r\n",__FILE__);
#endif
#if(HUB_API_TEST)
  hub_api_usart_msg_t pkt = {0};

  //02 02 05 00 a0 00 e8 78 03  panel 对hub事件的应答
  //02 03 05 00 a0 00 e8 78 03  panel 对rfm事件的应答

  //02 04 07 00 01 00 a5 5a 3B FB 03 panel设置初始化参数
  //02 05 08 00 02 01 00 a5 5a 97 11 03 panel设置RFM的QRFH
  //02 05 08 00 02 01 03 80 00 3c 7b 03 panel设置RFMid 4 的QRFH 布防
  //02 05 08 00 02 01 03 00 00 fc 1a 03 panel设置RFMid 4 的QRFH 撤防
  //02 06 08 00 03 02 03 ff 5a b3 e6 03 panel批量设置

  //02 16 05 00 10 00 28 0D 03 panel 设置hub软复位
  //02 17 05 00 10 01 E8 CC 03 panel 设置hub串口升级

  //02 07 0c 00 04 01 7f 03 09 50 5a a5 ff 4e 92 03 panel配置状态物模型

  //02 08 0c 00 05 01 00 60 55 55 55 01 01 08 03 03 panel配置操作物模型
  //02 08 10 00 05 01 00 60 55 55 55 01 01 61 01 02 03 D2 92 03 panel配置操作物模型
  //02 08 10 00 05 01 00 61 01 02 03 60 55 55 55 01 01 67 88 03 panel配置操作物模型

  //02 09 05 00 30 01 28 D5 03 获取RFM注册信息
  //02 0a 06 00 31 01 01 9f 3d 03 获取指定RFM的信息

  //02 07 04 00 32 D4 B1 03 获取网关电压温度
  //02 08 05 00 32 01 48 D4 03 获取网关电压温度

  //02 07 04 00 33 14 70 03 获取网关rssi
  //02 08 05 00 33 01 D8 D5 03 获取网关rssi

  //02 0b 05 00 60 01 28 e9 03 进入本地注册
  //02 0c 0c 00 61 01 02 03 04 05 06 07 08 e2 6c 03 MAC注册
  //02 0d 1c 00 62 a1 a2 a3 a4 a5 a6 a7 a8 1b 2b 3b 4b 5b 6b 7b 8b 9b 5a 51 52 53 54 55 56 3d b9 03 扫码注册
#if(1)
  //02 0e 18 00 63 01 00 01 10 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 e7 4d 03 同步广播
#else
  //02 0e 16 00 63 05 01 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 b1 03 同步广播布防
  //02 0e 16 00 63 05 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FD F4 03 同步广播布防
  //02 0e 24 00 63 05 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 03 00 0a 0b 04 03 06 00 01 02 03 04 05 17 CB 03 同步广播
  //02 0e 1B 00 63 02 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5a 03 f1 f2 f3 4F 3D 03 测试沾物模型
  //02 0e 1B 00 63 02 5a 03 f1 f2 f3 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 17 5C 03 测试沾物模型
  //02 0e 30 00 63 02 5a 03 f1 f2 f3 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 03 00 0a 0b 04 03 06 00 01 02 03 04 05 a5 05 91 92 93 94 95 C3 F4 03 测试沾物模型
#endif

#if(1)
  //02 0f 18 00 64 01 00 01 10 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 50 3b 03 普通广播 (保留bseq)
#else
  //02 0f 17 00 64 01 00 01 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 6b fe 03 普通广播 (保留bseq)
  //02 0f 16 00 64 01 01 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 73 96 03 普通广播 (没有bseq)
#endif

  //02 10 14 00 65 01 00 60 55 55 55 01 01 50 01 02 03 61 0a 0b 0c BC AF 03 点对点通信
  //02 10 0c 00 65 04 00 60 00 55 00 05 05 2A 74 03 遥控器点对点通信
  //02 10 14 00 65 01 00 60 61 62 63 64 65 61 66 67 68 50 51 52 53 C2 C0 03 点对点通信

  //02 10 19 00 65 01 00 60 61 62 63 64 65 61 66 67 68 50 51 52 53 5a 03 f1 f2 f3 9C F9 03 测试沾物模型
  //02 10 19 00 65 01 00 5a 03 f1 f2 f3 60 61 62 63 64 65 61 66 67 68 50 51 52 53 45 1C 03 测试沾物模型
  //02 10 20 00 65 01 00 5a 03 f1 f2 f3 60 61 62 63 64 65 61 66 67 68 50 51 52 53 a5 05 91 92 93 94 95 F3 B9 03 点对点通信

  //02 02 06 00 6D 00 00 DD 3D 03 //选择内置天线0
  //02 03 06 00 6D 01 00 4D 3C 03 //选择外置天线

  //02 11 0E 00 80 01 08 00 00 00 00 64 01 00 00 52 C4 03 //channel 0 txpower 100 发送载波 天线0
  //02 12 0E 00 80 01 08 00 00 00 00 00 00 00 00 A2 8A 03 //停止发送载波
  //02 13 0E 00 80 01 08 00 00 00 00 64 01 01 01 02 04 03 //channel 0 txpower 100 发送数据波 天线1
  //02 14 0A 00 80 02 04 00 00 00 7D 9B C5 03 //设置CTUNE125
  //02 15 07 00 80 03 01 28 E2 D9 03 //设置32768 CTUNE40

  //02 16 06 00 80 05 00 B8 AE 03 //读panid
  //02 17 07 00 80 05 01 01 3D F8 03 //读panid
  //02 18 09 00 80 06 03 01 02 03 44 07 03 //写panid

  //02 11 06 00 69 04 09 DA BE 03
  //02 12 14 00 6B 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00 FC D9 03 序列号注册
  //02 12 10 00 6B 44 47 30 30 38 30 4E 30 30 30 30 31 A3 87 03 序列号注册
  //02 12 14 00 6B 44 47 30 30 38 30 4E 30 30 30 30 31 32 33 34 35 c6 01 03 序列号注册
  //02 12 10 00 6B 44 48 30 30 38 30 4E 30 30 30 30 31 B7 B7 03 序列号注册

  //02 13 14 00 6A 01 05 01 02 03 04 05 FE 07 FF 03 00 00 1C 00 00 27 DA 03 //开始OTA

  //02 14 04 00 6E ED B1 03 //停止广播

  unsigned char buf[8][255] = {
      {11, 0x02, 0x01, 0x07, 0x00, 0x01, 0x01, 0xa5, 0x5a, 0xfb, 0xaa, 0x03}, //模拟FCODE 0x01
      {12, 0x02, 0x02, 0x08, 0x00, 0x02, 0x01, 0x00, 0xa5, 0x5a, 0x97, 0x11, 0x03},//模拟FCODE 0x02
      {12, 0x02, 0x03, 0x08, 0x00, 0x03, 0x02, 0x03, 0xff, 0x5a, 0xb3, 0xe6, 0x03}, //模拟FCODE 0x03
      {11, 0x02, 0x04, 0x07, 0x00, 0x03, 0x03, 0x0a, 0x5a, 0x73, 0x77, 0x03}, //模拟FCODE 0x03
      {18, 0x02, 0x05, 0x0e, 0x00, 0x04, 0x01, 0x7f, 0x03, 0x01, 0x09, 0x50, 0x03, 0x5a, 0xa5, 0xff, 0xa5, 0xfe, 0x03}, //模拟FCODE 0x04
      {18, 0x02, 0x06, 0x0e, 0x00, 0x04, 0x01, 0x7f, 0x50, 0x03, 0x5a, 0xa5, 0xff, 0x03, 0x01, 0x09, 0xff, 0x02, 0x03}, //模拟FCODE 0x04
      {9,  0x02, 0x07, 0x05, 0x00, 0x30, 0x01, 0x28, 0xd5, 0x03},//模拟FCODE 0x30
      {10, 0x02, 0x08, 0x06, 0x00, 0x31, 0x01, 0x01, 0x9f, 0x3d, 0x03}, //模拟FCODE 0x31
  };
  unsigned int i,j = 0;
  unsigned int iret = 1;
  for(j = 0; j < 8; j++){
      for(i = 0; i < buf[j][0]; i++){
          iret = DS_hub_api_usart_msg_parse(buf[j][i+1], &pkt);
          if(iret == 0){
              DS_hub_api_creat_usart_rx_event(&pkt);
          }else if(iret != 1){
              DS_app_log_error("iret %d\r\n",iret);
          }
      }
  }
  unsigned char data = 0x01;
  DS_hub_api_creat_hub_event(0x02, &data, 1);

  unsigned char rollingcode[4] = {0x00,0x00,0x00,0x66};
  unsigned char dbginfo[2] = {0x00,0x00};
  unsigned char payload[25] = {0x22, 0x11, 0x01, 0x01, 100, 50, 25, 0x00,
      0x00, 0x01, 0xb0, 0xb0, 0xb0, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22,
      0x11, 0x00, 0x00, 0x01, 0x01};
  DS_hub_api_creat_rfm_event(149, rollingcode, 0x9b, dbginfo, 0x03, payload, 25);
#endif
#if(0)
  static int test_count = 300;

  unsigned char code[4] = {0};
  unsigned char dbginfo[2] = {0};
  unsigned char payload[3] = {0x10,0x01,0x01};

  unsigned char delay_txtask = 0;
  getThisParam(ENbyDelayTxTask, &delay_txtask);
  if(delay_txtask){
      return;
  }

  if(!test_count){
      return;
  }
  DS_hub_api_creat_rfm_event(
      1,
      code,
      100,
      dbginfo,
      0xff,
      payload,
      3
      );

  if(test_count){
      test_count--;
  }
#endif
#if(0) //文件最大缓存测试，最多能存98条
  static int test_count = 0;
  unsigned char payload[230] = {0};
  payload[0] = 0;
  payload[1] = 1;
  if(filepayload_cache_to_file_link(payload,230) == 0){
      test_count++;
  }else{

  }
#endif
}
